library HeroRevive requires Revive

    globals
        // 释放灵魂技能ID
        private constant integer RELEASE_SOUL_SPELL_ID = 'A05S'
        // 买活物品ID
        private constant integer BUY_REVIVE_ITEM_ID = 'I001'
        // 灵魂单位ID
        private constant integer UNITTYPE_SOUL = 'h000'
        // 墓碑单位ID
        private constant integer UNITTYPE_GRAVE = 'h001'
    endglobals


struct HeroRevive
    delegate Revive m_revive

    unit m_grave
    unit m_soul
    effect m_model
    effect m_cloud

    implement StructList

    static method get takes Unit ud returns thistype
        local thistype d = thistype.first
        loop
            exitwhen (d <= 0)
            if d.m_ud == ud then
                return d
            endif
            set d = d.next
        endloop
        return 0
    endmethod

    static method searchByOther takes unit u returns thistype
        local thistype d = thistype.first
        loop
            exitwhen (d == 0)
            if d.m_grave == u or d.m_soul == u then
                return d
            endif
            set d = d.next
        endloop
        return 0
    endmethod

    static method create takes Unit ud returns thistype
        local thistype this = thistype.allocate()
        set this.m_revive = Revive.create(ud)
        call this.listAdd()
        return this
    endmethod

    method clear takes nothing returns nothing
        call PauseTimer(this.m_timer)
        call DestroyEffect(this.m_model)
        call DestroyEffect(this.m_cloud)
        call RemoveUnit(this.m_grave)
        call RemoveUnit(this.m_soul)
        set this.m_model = null
        set this.m_cloud = null
        set this.m_grave = null
        set this.m_soul = null
    endmethod

    method destroy takes nothing returns nothing
        call this.clear()
        call this.m_revive.destroy()
        call this.listRemove()
        call this.deallocate()
    endmethod

    private static method anon__1 takes nothing returns nothing
        local thistype this = GetTimerData(GetExpiredTimer())
        //852600通魔
        call IssueImmediateOrderById(this.m_grave, 852600)
        call SetUnitAnimationByIndex(this.m_grave, 0)
        call SetUnitOwner(this.m_grave, GetOwningPlayer(this.m_ud.m_unit), true)
        call ShowUnit(this.m_grave, true)
        call RefreshUnitEffectColor()
        call SelectUnitForPlayerSingle(this.m_grave, GetOwningPlayer(this.m_ud.m_unit))
    endmethod

    method createGrave takes player ownner, integer graveUnitType returns unit
        local real x = GetUnitX(this.m_ud.m_unit)
        local real y = GetUnitY(this.m_ud.m_unit)

        set this.m_grave = CreateUnit(ownner, graveUnitType, x, y, bj_UNIT_FACING)
        call ShowUnit(this.m_grave, false)
        call SetUnitInvulnerable(this.m_grave, true)
        call SetUnitAttackable(this.m_grave, false)
        call SetUnitMoveable(this.m_grave, false)
        call UnitShareVisionForAlly(this.m_grave, true)

        call TimerStart(this.getTimer(), 2.00, false, function thistype.anon__1)
        return this.m_grave
    endmethod

    private method panCamera takes Unit ud returns nothing
    endmethod

    private method doRevive takes real x, real y, real rateState returns nothing
        local unit hero
        if IsUnitAlive(this.m_ud.m_unit) then
            return
        endif
        set hero = this.m_ud.m_unit
        call ReviveHero(hero, x, y, false)
        call AddEffectTarget("Abilities\\Spells\\Human\\ReviveHuman\\ReviveHuman.mdl", hero, "origin")

        call SetUnitLifeBJ(hero, GetUnitState(hero, UNIT_STATE_MAX_LIFE) * rateState)
        call SetUnitManaBJ(hero, GetUnitState(hero, UNIT_STATE_MAX_MANA) * rateState)
        call SelectUnitForPlayerSingle(hero, GetOwningPlayer(hero))

        call this.panCamera(this.m_ud)
        call this.clear()
        set hero = null
    endmethod
    /**
     * 方式3 救活
     * @param unit u 复活施放者
     * @param unit ug 灵魂或墓碑
     * @param real rateState  复活后生命魔法比例
     * @return
     */
    static method reviveFromGrave takes unit u, unit ug, real rateState returns nothing
        local HeroRevive hr = HeroRevive.searchByOther(ug)
        call hr.doRevive(GetUnitX(u), GetUnitY(u), rateState)
    endmethod

    private static method anon__2 takes nothing returns nothing  //虚无
        local HeroRevive hr = GetTimerData(GetExpiredTimer())
        local real soulX = GetUnitX(hr.m_soul)
        local real soulY = GetUnitY(hr.m_soul)
        local real graveX = GetUnitX(hr.m_grave)
        local real graveY = GetUnitY(hr.m_grave)


        local real dis = GetDistanceByXY(soulX, soulY, graveX, graveY)
        if dis <= 400.00 then
            call hr.doRevive(soulX, soulY, 0.3)
        endif
    endmethod
    /**
     * 方式2 跑尸
     * @return
     */
    static method createSoul takes nothing returns nothing
        local thistype hr = thistype.searchByOther(SpellEvent.CastingUnit)
        local real x = hr.m_reviveX
        local real y = hr.m_reviveY
        local real scale = hr.m_ud.m_modelScale
        local Unit ud

        if GetOwningPlayer(hr.m_grave) != Player(PLAYER_NEUTRAL_PASSIVE) then
            call UnitRemoveAbility(hr.m_grave, RELEASE_SOUL_SPELL_ID)

            set hr.m_soul = CreateUnit(GetOwningPlayer(hr.m_ud.m_unit), UNITTYPE_SOUL, x, y, GetRandomReal(0, 360))
            set hr.m_model = AddSpecialEffectTarget(hr.m_ud.m_model, hr.m_soul, "origin")
            set hr.m_cloud = AddSpecialEffectTarget("DrEffect\\BanishTarget.mdl", hr.m_soul, "origin")

            call RefreshUnitEffectColor()

            call UnitAddAbility(hr.m_soul, 'Aetl')

            set ud = Unit.get(hr.m_soul)
            call hr.panCamera(ud)

            if (GetLocalPlayer() == GetOwningPlayer(hr.m_soul)) then
                call PanCameraToTimed(x, y, 0)
                call ClearSelection()
                call SelectUnit(hr.m_soul, true)
            endif

            call AddEffectTarget("Abilities\\Spells\\Undead\\AnimateDead\\AnimateDeadTarget.mdl", hr.m_soul, "origin")
            call TimerStart(hr.getTimer(), 0.10, true, function thistype.anon__2)
        endif
    endmethod
    /**
     * 方式1 买活
     * @param  {[type]} unit u             操作单位
     * @param  {[type]} item it            买活物品
     */
    static method buyRevive takes unit u, item it returns nothing
        local thistype hr
        if BUY_REVIVE_ITEM_ID != GetItemTypeId(it) then
            return
        endif
        if GetUnitTypeId(u) == UNITTYPE_SOUL then
            set hr = thistype.searchByOther(u)
            call hr.doRevive(GetUnitX(u), GetUnitY(u), 0.02)
        else
            call SimError(GetOwningPlayer(u), "只有灵魂才能这样做")
            call SetPlayerState(GetOwningPlayer(u), PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(GetOwningPlayer(u), PLAYER_STATE_RESOURCE_GOLD) + 10)
        endif
    endmethod

    static method death takes unit u returns nothing
        local Unit ud = Unit.get(u)
        local HeroRevive hr

        if IsPlayerControllerIsUser(GetOwningPlayer(u)) then
            //TODO
            set hr = HeroRevive.get(ud)
            if not (IsUnitAlive(ud.m_unit)) and hr.m_isEnable then
                call hr.createGrave(Player(PLAYER_NEUTRAL_PASSIVE), UNITTYPE_GRAVE)
                call UnitAddAbility(hr.m_grave, RELEASE_SOUL_SPELL_ID) //释放
                call ClearTextMessages()
                call DisplayTimedTextToForce(bj_FORCE_ALL_PLAYERS, 0.00, " ")
            endif
        endif
    endmethod

    static method init takes nothing returns nothing
        call RegisterSpellCastResponse(RELEASE_SOUL_SPELL_ID, thistype.createSoul)
        call RegisterPickupItemResponse(thistype.buyRevive)
        call RegisterUnitDeathResponse(thistype.death)
    endmethod
endstruct


endlibrary